#include "QxAllSampleFactory.hpp"
#include "QxSampleFactory.hpp"

#include <Base/QxAbstractPlugin.hpp>

#include <QDir>
#include <QMap>
#include <QFileInfo>
#include <QCoreApplication>

class QxAllSampleFactory::QxAllSampleFactoryPrivate
{
public:

  QxAllSampleFactoryPrivate( QxAllSampleFactory* me ) : m_self( me ) {
  }

  ~QxAllSampleFactoryPrivate() {
    qDeleteAll( m_factories.values() );
  }

  void init() {
    QDir appDir( QCoreApplication::applicationDirPath() );
    appDir.cdUp();
    if( appDir.cd( "plugins" ) ) {
      QStringList folders = appDir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
      Q_FOREACH( const QString& folder, folders ) {
        if( QFileInfo( appDir.absoluteFilePath( folder ) ).isDir() ) {
          m_factories[folder] = new QxSampleFactory( folder );
          m_factories[folder]->setParent( m_self );
        }
      }
    }
  }

  QxAllSampleFactory*               m_self;

  QMap<QString, QxAbstractFactory*> m_factories;
};

const QxAllSampleFactory& QxAllSampleFactory::instance()
{
  static QxAllSampleFactory factory;

  return factory;
}

QxAllSampleFactory::~QxAllSampleFactory()
{
}

QString QxAllSampleFactory::name() const
{
  return tr( "Qt Examples and Demos" );
}

QString QxAllSampleFactory::description() const
{
  return tr( "All Sample Factories" );
}

QStringList QxAllSampleFactory::categories() const
{
  return _pd->m_factories.keys();
}

QStringList QxAllSampleFactory::pluginNameList( const QString& category ) const
{
  QStringList result;

  QStringList categories = this->categories();
  if( categories.contains( category ) ) {
    Q_FOREACH( QxAbstractPlugin* plugin, _pd->m_factories[category]->getPlugins<QxAbstractPlugin>() ) {
      if( plugin ) {
        result << plugin->name();
      }
    }
  }

  return result;
}

QxAbstractPlugin* QxAllSampleFactory::findPluginByName( const QString& pluginName ) const
{
  Q_FOREACH( QxAbstractFactory* factory, _pd->m_factories.values() ) {
    Q_FOREACH( QxAbstractPlugin* plugin, factory->getPlugins<QxAbstractPlugin>() ) {
      if( plugin && !plugin->name().compare( pluginName, Qt::CaseInsensitive ) ) {
        return plugin;
      }
    }
  }

  return 0;
}

QxAllSampleFactory::QxAllSampleFactory() : QxAbstractFactory( "" ), _pd( new QxAllSampleFactoryPrivate( this ) )
{
  _pd->init();
}
